//
//  GMGifPlayer.m
//  GMLive
//
//  Created by gmlive on 17/4/22.
//  Copyright © 2017年 gmlive. All rights reserved.
//

#import "GMGifPlayer.h"
#import <AVFoundation/AVFoundation.h>
#import <ImageIO/ImageIO.h>

@interface GMGifPlayer ()
{
    CGImageSourceRef _imageSourceRef;
    void * bytes[40];
    NSMutableArray<NSData *> *dataArr;
    NSMutableArray<NSValue *> *sizeArr;
    NSTimer *timer;
    size_t index;
    NSUInteger numberOfFrames;
    
    AVAudioPlayer *audioPlayer;
}

@property (nonatomic,assign,readwrite) BOOL isAnimating;
@property (nonatomic,assign,readwrite) BOOL isPause;

@end

@implementation GMGifPlayer

//获取当前ref的时间
inline static NSTimeInterval CGImageSourceGetGifFrameDelay(CGImageSourceRef imageSource, NSUInteger index)
{
    NSTimeInterval frameDuration = 0;
    CFDictionaryRef theImageProperties;
    if ((theImageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, index, NULL))) {
        CFDictionaryRef gifProperties;
        if (CFDictionaryGetValueIfPresent(theImageProperties, kCGImagePropertyGIFDictionary, (const void **)&gifProperties)) {
            const void *frameDurationValue;
            if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFUnclampedDelayTime, &frameDurationValue)) {
                frameDuration = [(__bridge NSNumber *)frameDurationValue doubleValue];
                if (frameDuration <= 0) {
                    if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFDelayTime, &frameDurationValue)) {
                        frameDuration = [(__bridge NSNumber *)frameDurationValue doubleValue];
                    }
                }
            }
        }
        CFRelease(theImageProperties);
    }
    
#ifndef OLExactGIFRepresentation
    //Implement as Browsers do.
    //See:  http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser-compatibility
    //Also: http://blogs.msdn.com/b/ieinternals/archive/2010/06/08/animated-gifs-slow-down-to-under-20-frames-per-second.aspx
    
    if (frameDuration < 0.02 - FLT_EPSILON) {
        frameDuration = 0.1;
    }
#endif
    return frameDuration;
}

- (instancetype)initWithFileName:(NSString *)filename
{
    if (self = [self initWithGifName:filename musicName:nil]) {
        
    }
    
    return self;
}

- (instancetype)initWithGifName:(NSString *)filename musicName:(NSString *)music
{
    if (self = [super init]) {
        
        NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:nil];
        if (!path) {
            return nil;
        }
        NSData *data = [NSData dataWithContentsOfFile:path];
        _imageSourceRef = CGImageSourceCreateWithData((CFDataRef)data, NULL);
        
        if (!_imageSourceRef) {
            return nil;
        }
        
        numberOfFrames = CGImageSourceGetCount(_imageSourceRef);
        
        //创建所有图片的数值
        sizeArr = [NSMutableArray arrayWithCapacity:numberOfFrames];
        dataArr = [NSMutableArray arrayWithCapacity:numberOfFrames];
        
        for (NSUInteger i = 0; i < numberOfFrames; ++i) {
            NSTimeInterval frameDuration = CGImageSourceGetGifFrameDelay(_imageSourceRef, i);
            self.totalDuratoin += frameDuration;
        }
        
        for (int i=0; i<numberOfFrames; i++) {
            //替换读取到的每一张图片
            CGImageRef image = CGImageSourceCreateImageAtIndex(_imageSourceRef, i, NULL);
            
            // Access the raw image bytes directly
            CFDataRef dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider(image));
            
            [dataArr addObject:(__bridge NSData * _Nonnull)(dataFromImageDataProvider)];
            
            [sizeArr addObject:[NSValue valueWithCGSize:CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image))]];
            
            if (dataFromImageDataProvider)
            {
                CFRelease(dataFromImageDataProvider);
            }
            CFRelease(image);
        }
        
        if (music) {
            path = [[NSBundle mainBundle] pathForResource:music ofType:nil];
            if (path) {
                NSURL *musicUrl = [NSURL URLWithString:path];
                if (musicUrl) {
                    audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicUrl error:nil];
                    audioPlayer.numberOfLoops = 100000;
                }
            }
        }
    }
    
    return self;
}

- (void)setTotalDuratoin:(NSTimeInterval)totalDuratoin
{
    _totalDuratoin = totalDuratoin;
    
    if ([timer isValid]) {
        [timer invalidate];
        timer = nil;
    }
    
    if (_isAnimating) {
        [self startGIF];
    }
}

-(void)startGIF
{
    if (_isAnimating) {
        return;
    }
    //开始动画，启动一个定时器，每隔一段时间调用一次方法，切换图片
    if (timer == nil) {
        timer = [NSTimer scheduledTimerWithTimeInterval:self.totalDuratoin / numberOfFrames target:self selector:@selector(play) userInfo:nil repeats:YES];
    }
    [timer fire];
    
    [audioPlayer play];
    self.isAnimating = YES;
    self.isPause = NO;
    
}

- (void)pause
{
    if (_isAnimating) {
        [audioPlayer pause];
        [timer invalidate];
        timer = nil;
        self.isPause = YES;
        self.isAnimating = NO;
    }
}

- (void)stopGIF
{
    if (timer) {
        [timer invalidate];
        timer = nil;
    }
    
    [audioPlayer stop];
    
    self.isAnimating = NO;
}

-(void)play
{
    index = index + 1;
    index=  index % numberOfFrames;
   
    if ([self.delegate respondsToSelector:@selector(gifPlayer:didOutPutImageByte:WithSize:)]) {
        CFDataRef data = (__bridge CFDataRef)(dataArr[index]);
        GLubyte *imageData = (GLubyte *)CFDataGetBytePtr(data);
        [self.delegate gifPlayer:self didOutPutImageByte:imageData WithSize:sizeArr[index].CGSizeValue];
    }
}

- (void)dealloc
{
    CFRelease(_imageSourceRef);
    
    if (timer) {
        [timer invalidate];
        timer = nil;
    }
    
}

@end
